import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.lang.Math;

/**
 * Esta clase representa al lanzador de misiles.
 * @author Miguel Martinez Aguilar
 * @version 25 de Marzo del 2013
 */
public class Lanzador extends ScrollActor
{
    // Declaracion de variables de instancia
    private int xf;// es la coordenada (x) final de un proyectil.
    private int yf;// es la coordenada (y) final de un proyectil.
    private boolean izder;// boleano que indica hacia donde esta orientado el lanzador.
    private boolean tiro;// boleano que indica si se a realizado un tiro.
    private boolean impacto;// boleano que establece si existe un impacto.
    private boolean hayBarco;// boleano que indica si en el espacio destruido se encontro un barco.
    private boolean destruido;// boleano que indica si el barco encontrado fue destruido.
    private double vox;// velocidad inicial en la coordenada x.
    private double tiempo;// tiempo que tardara un proyectil en impactar.
    private double gravedad;// gravedad que jala al proyectil hacia abajo en el escenario.
    private double altura;// altura desde la que el proyectil realizara su descenso.
    private double distancia;// distancia en X del lanzador al espacio a destruir.
    private Espacio esp;// espacio a destruir.
    private Panel panel;// el panel que controla el juego.
    private GreenfootImage[] img;// un arreglo de 2 imagenes que indican la orientacion del lanzador.

     /**
     * Este es el constructor de lanzador.
     * @param panel: el panel al que se dirigira el lanzador.
     */
    public Lanzador(Panel panel) 
    {
        img = new GreenfootImage[2];
        img[0] = new GreenfootImage("lanzadord.png");
        img[1] = new GreenfootImage("lanzadori.png");
        xf = yf = 0;
        izder = false;
        gravedad = 2;
        vox = tiempo = altura = distancia =0;
        this.esp = null;
        this.tiro = false;
        this.impacto = this.hayBarco = this.destruido = false;
        this.panel = panel;
    }
    
    /**
     * Este metodo lanza un proyectil.
     * @param arma: un numero que indique el tipo de arma que el jugador utilizara contra su oponente.<p>
     * los numeros van del 0 al 3.
     */
    public void lanzaProyectil(int arma)
    {
        Proyectil nuevo = null;
        ScrollWorld mundo = super.getWorld();
        this.actualizaValores();
        nuevo = this.creaProyectil(arma);
        if(!izder)mundo.addObject(nuevo, this.getGlobalX() + 20, this.getGlobalY() + 18);
        else{
            mundo.addObject(nuevo, this.getGlobalX() - 20, this.getGlobalY() + 18);
            nuevo.turn(180);
        }
        Greenfoot.playSound("boom.wav");
    }
    
    /**
     * Este metodo crea un proyectil. <p>
     * Regresa un proyectil.
     * @param arma: un numero que indique el tipo de arma que el jugador utilizara contra su oponente.<p>
     * los numeros van del 0 al 3.
     */
    public Proyectil creaProyectil(int arma)
    {
        Proyectil nuevo = null;
        if(arma == 0){
            if(!izder)nuevo = new Bala(this,this.getX() + 26,this.getY() + 18,tiempo,gravedad,vox,esp);
            else nuevo = new Bala(this,this.getX() - 26,this.getY() + 18,tiempo,gravedad,vox,esp);
        }
        if(arma == 1){
            if(!izder)nuevo = new GranadaH(this,this.getX() + 26,this.getY() + 18,tiempo,gravedad,vox,esp);
            else nuevo = new GranadaH(this,this.getX() - 26,this.getY() + 18,tiempo,gravedad,vox,esp);
        }
        if(arma == 2){
            if(!izder)nuevo = new GranadaV(this,this.getX() + 26,this.getY() + 18,tiempo,gravedad,vox,esp);
            else nuevo = new GranadaV(this,this.getX() - 26,this.getY() + 18,tiempo,gravedad,vox,esp);
        }
        if(arma == 3){
            if(!izder)nuevo = new Bomba(this,this.getX() + 26,this.getY() + 18,tiempo,gravedad,vox,esp);
            else nuevo = new Bomba(this,this.getX() - 26,this.getY() + 18,tiempo,gravedad,vox,esp);
        }
        return nuevo;
    }
    
    /**
     * Este metodo actualiza valores para las variables de instancia
     */
    public void actualizaValores()
    {
        if(!izder)distancia = xf - (this.getX() + 20);
        else distancia = xf - (this.getX() - 20);
        altura = yf - (this.getY() + 18);
        tiempo = Math.sqrt(altura / (gravedad / 2));
        vox = distancia / tiempo;
        vox = Math.round(vox);
    }
    
    /**
     * Este metodo cambia xf y yf.
     * @param lugar: un Espacio que esta en la mira para destruir.
     */
    public void defineDireccion(Espacio lugar)
    {
        this.esp = lugar;
        xf = esp.getX();
        yf = esp.getY();
    }
    
    /**
     * Este metodo cambia la orientacion del lanzador.
     * @param der: indica la orientacio del Lanzador.
     */
    public void derecha(boolean der)
    {
        if(der)this.setImage(img[0]);
        else this.setImage(img[1]);
        izder = der;
    } 
    
    /**
     * Este metodo modifica el valor de tiro.
     * @param val: un booleano que indica si se realizo un tiro.
     */
    public void lanzamiento(boolean val)
    {
        this.tiro = val;
    }
    
    /**
     * Este metodo regresa el valor de tiro. <p>
     * Regresa un boleano.
     */
    public boolean lanzamiento()
    {
        return tiro;
    } 
    
    /**
     * Este metodo regresa el valor de impacto. <p>
     * Regresa un boleano.
     */
    public boolean impacto()
    {
        return impacto;
    }
    
    /**
     * Este metodo modifica el valor de impacto.
     * @param val: un booleano que indica si se dio el impacto.
     */
    public void impacto(boolean val)
    {
        this.impacto = val;
    }
    
    /**
     * Este metodo indica a panel que termina o inicia el juego del usuario.
     * @param val: un booleano que indica si se termina el turno de un jugador.
     */
    public void cambiaTurno(boolean val)
    {
        panel.cambiaTurno(val);
    }
    
    /**
     * Este metodo modifica el valor de hayBarco
     * @param val: un booleano que indica si se encontro un barco en el impacto del proyectil.
     */
    public void hayBarco(boolean val)
    {
        hayBarco = val;
    }
    
    /**
     * Este metodo regresa el valor de hayBarco. <p>
     * Regresa un boleano.
     */
    public boolean hayBarco()
    {
        return hayBarco;
    }
    
    /**
     * Este metodo indica si se ha destruido un barco.
     * @param val: un booleano que indica si se ha destruido un barco.
     */
    public void barcoDestruido(boolean val)
    {
        destruido = val;
    }
    
    /**
     * Este metodo devuelve el valor de destruido. <p>
     * Regresa un boleano.
     */
    public boolean barcoDestruido()
    {
        return destruido;
    }
    
    /**
     * Este metodo genera una espera para derrotar un barco. <p>
     * Regresa un boleano.
     */
    public boolean explotaBarco()
    {
        boolean val = panel.explotaBarco();
        if(val)if(destruido)panel.derrotaBarco(!izder);
        return val;
    }
}